// #ifndef UTIL_H
// #define UTIL_H

// //这是该项目中的工具头文件，定义了众多的工具。
// #include "config.h"
// #include <arpa/inet.h>  //用于地址转换，即将一些网络地址格式从一种形式转换为另一种形式。
// #include <boost/archive/text_iarchive.hpp>
// #include <boost/archive/text_oarchive.hpp>
// #include <boost/serialization/access.hpp>
// #include <chrono>
// #include <condition_variable>  // pthread_condition_t
// #include <fstream>
// #include <functional>
// #include <iostream>
// #include <mutex>  // pthread_mutex_t
// #include <ostream>
// #include <queue>
// #include <random>
// #include <sstream>
// #include <string>
// #include <sys/socket.h>
// #include <thread>
// #include <unistd.h>  //unistd.h为Linux/Unix系统中内置头文件，包含了许多系统服务的函数原型，例如read函数、write函数和getpid函数等。

// //延迟处理函数功能实现，使用模板类
// class ScopExit
// {
// public:
//     explicit ScopExit( std::function< void() > cb )
//         : m_cb( cb )
//         , m_dismissed( false )
//     {
//     }
//     ~ScopExit()
//     {
//         if ( !m_dismissed )
//         {
//             m_cb();
//         }
//     }

//     ScopExit( const ScopExit & ) = delete;
//     ScopExit &operator=( const ScopExit & ) = delete;

//     //允许显式地取消执行
//     void dismiss() { m_dismissed = true; }

// private:
//     std::function< void() > m_cb;
//     bool m_dismissed;
// };

// //声明打印调试信息方法
// void Dprintf( const char *format, ... );

// //错误处理函数
// void myAssert( bool condition, std::string message );  //给参数赋予默认值

// //命令参数拼接
// template < typename... Args >
// std::string format( const char *format_str, Args... args )
// {
//     std::stringstream ss;
//     int _[] = { ( ( ss << args ), 0 )... };
//     ( void )_;
//     return ss.str();
// }
// //获取高精度时间
// std::chrono::_V2::system_clock::time_point now();

// //选举超时
// std::chrono::microseconds getRandomizedElectionTimeout();

// //休眠时间
// void sleepNMilliseconds( int n );

// template < typename T >
// class LockQueue
// {
// private:
//     std::queue< T > m_queue;
//     std::mutex m_mutex;
//     std::condition_variable m_condvariable;

// public:
//     //不写构造函数，会默认使用默认构造函数
//     void push( const T &data )
//     {
//         std::lock_guard< std::mutex > lock( m_mutex );  //给队列上锁
//         m_queue.push( data );
//         m_condvariable.notify_one();  //唤醒条件等待的线程
//     }

//     T Pop()
//     {
//         std::unique_lock< std::mutex > lock( m_mutex );  //上锁
//         while ( m_queue.empty() )
//         {
//             m_condvariable.wait( lock );  //如果队列为空，则阻塞线程
//         }
//         T data = m_queue.front();  //获取队列的数据
//         m_queue.pop();
//         return data;
//     }

//     //添加一个超时等待的机制
//     bool timeOutPop( int timeout, T *ResData )
//     {
//         std::unique_lock< std::mutex > lock( m_mutex );

//         //获取当前时间
//         // time()方法也是获取当前时间但是单位是描述，不提供更高精度的分辨率，因此不适用当前功能
//         // std::chrono::system_clock::now() 获取高精度的时间数据，提供毫秒，微秒，纳秒精度。
//         // time_point 对象可以与 <chrono>
//         // 库中的其他时间工具配合使用，例如持续时间计算、时间差异计算等。
//         auto now = std::chrono::system_clock::now();
//         auto timeout_time = now + std::chrono::microseconds( timeout );

//         while ( m_queue.empty() )
//         {
//             /*
//                 std::cv_status::timeout 是 C++ 中用于表示条件变量等待超时的枚举值之一。
//                 在 C++ 标准库中，条件变量的 wait_for 和 wait_until
//                 成员函数可以用于等待某个条件的满足，这两个函数都返回一个 std::cv_status
//                 枚举值，指示等待的状态。
//                 std::cv_status::timeout 表示等待操作因超时而结束，条件未满足。
//                 std::cv_status::no_timeout 表示等待操作因条件满足而结束
//             */
//             if ( m_condvariable.wait_until( lock, timeout_time ) == std::cv_status::timeout )
//             {
//                 return false;
//             }
//             *ResData = m_queue.front();
//             m_queue.pop();
//             return true;
//         }
//     }
// };
// /*
//     两个对锁的管理用到了RAII的思想，防止中途出现问题而导致资源无法释放的问题！！！
//     std::lock_guard 和 std::unique_lock 都是 C++11 中用来管理互斥锁的工具类，它们都封装了
//    RAII（Resource Acquisition Is Initialization）技术，使得互斥锁在需要时自动加锁，
//     在不需要时自动解锁，从而避免了很多手动加锁和解锁的繁琐操作。
//     std::lock_guard 是一个模板类，它的模板参数是一个互斥量类型。当创建一个 std::lock_guard
//     对象时，它会自动地对传入的互斥量进行加锁操作，并在该对象被销毁时对互斥量进行自动解锁操作。std::lock_guard
//     不能手动释放锁，因为其所提供的锁的生命周期与其绑定对象的生命周期一致。 std::unique_lock
//     也是一个模板类，同样的，其模板参数也是互斥量类型。不同的是，std::unique_lock
//    提供了更灵活的锁管理功能。可以通过 lock()、unlock()、try_lock()
//    等方法手动控制锁的状态。当然，std::unique_lock 也支持 RAII
//     技术，即在对象被销毁时会自动解锁。另外， std::unique_lock 还支持超时等待和可中断等待的操作。
// */

// //定义kv数据库对raft的操作类
// class Op
// {
// public:
//     std::string Operation;  //"Get","Put","Append"
//     std::string Key;
//     std::string Value;
//     std::string ClientId;  //客户端号码
//     int RequestId;         //客户端号码请求的Request的序列号，为了保证线性一致性。
// public:
//     std::string asString() const
//     {
//         //创建文本输出流
//         std::ofstream fout( "history.txt" );
//         //创建字符串流
//         std::stringstream ss;
//         boost::archive::text_oarchive oa1( fout );  //文本的输出归档类，使用fout来构造
//         boost::archive::text_oarchive oa2( ss );
//         oa1 << *this;
//         oa2 << *this;

//         fout.close();

//         return ss.str();
//     }

//     //反序列化，将字符串反序列化当前对象的数据
//     bool parseFromString( std::string str )
//     {
//         std::stringstream iss( str );  //将字符串放入到字符串流中
//         //使用iss来构造反序列化对象ia,这个对象使用iss作为输入流，用于读取数据
//         boost::archive::text_iarchive ia( iss );
//         ia >> *this;
//         return true;
//     }

// public:
//     //实现了将 Op 类的实例的状态格式化为一种易读的字符串形式，然后输出到任何 std::ostream 类型的对象
//     friend std::ostream &operator<<( std::ostream &os, const Op &obj )
//     {
//         os << "[MyClass:Operation{" + obj.Operation + "},Key{" + obj.Key + "},Value{" + obj.Value + "},ClientId{" + obj.ClientId + "},RequestId{"
//                   + std::to_string( obj.RequestId ) + "}";  // 在这里实现自定义的输出格式
//         return os;
//     }

// private:
//     friend class boost::serialization::access;

//     //定义一个序列化或反序列化功能，将该类的实体序列化后进行传输或存储。或使用序列化的数据来重构对象
//     template < typename Archive >
//     void serialize( Archive &ar, const unsigned int version )
//     {
//         //在这里使用引用，因为是类数类型，指针一般用在内置数据类型、数组和结构体时时。
//         ar &Operation;
//         ar &Key;
//         ar &Value;
//         ar &ClientId;
//         ar &RequestId;
//     }
// };
// //判断端口是否被占用

// const std::string OK = "OK";
// const std::string ErrNoKey = "ErrNoKey";
// const std::string ErrWrongLeader = "ErrWrongLeader";

// bool isReleasePort( unsigned short usport );

// bool getReleasePort( short &port );

// #endif